package main

import (
	"fmt"
	"time"
)

// Product - 日志配置
type LogConfig struct {
	Level         string
	Format        string
	Outputs       []LogOutput
	Filters       []LogFilter
	Rotation      RotationConfig
	BufferSize    int
	FlushInterval time.Duration
	Timezone      *time.Location
	IncludeFields []string
	ExcludeFields []string
	Metadata      map[string]interface{}
}

type LogOutput struct {
	Type     string
	Target   string
	Format   string
	MinLevel string
	MaxLevel string
}

type LogFilter struct {
	Field     string
	Operation string
	Value     interface{}
}

type RotationConfig struct {
	MaxSize    int64
	MaxAge     time.Duration
	MaxBackups int
	Compress   bool
}

func (lc *LogConfig) Display() {
	fmt.Printf("日志配置:\n")
	fmt.Printf("  级别: %s\n", lc.Level)
	fmt.Printf("  格式: %s\n", lc.Format)
	fmt.Printf("  输出数量: %d\n", len(lc.Outputs))
	fmt.Printf("  过滤器数量: %d\n", len(lc.Filters))
	fmt.Printf("  缓冲区大小: %d\n", lc.BufferSize)
	fmt.Printf("  刷新间隔: %v\n", lc.FlushInterval)
	fmt.Printf("  时区: %s\n", lc.Timezone.String())
	fmt.Printf("  包含字段: %v\n", lc.IncludeFields)
	if len(lc.ExcludeFields) > 0 {
		fmt.Printf("  排除字段: %v\n", lc.ExcludeFields)
	}
}

// Abstract Builder - 抽象建造者
type LogConfigBuilder interface {
	SetLevel(level string) LogConfigBuilder
	SetFormat(format string) LogConfigBuilder
	AddOutput(output LogOutput) LogConfigBuilder
	AddFilter(filter LogFilter) LogConfigBuilder
	SetRotation(rotation RotationConfig) LogConfigBuilder
	SetBuffer(size int, flushInterval time.Duration) LogConfigBuilder
	SetTimezone(timezone *time.Location) LogConfigBuilder
	IncludeField(field string) LogConfigBuilder
	ExcludeField(field string) LogConfigBuilder
	SetMetadata(key string, value interface{}) LogConfigBuilder
	Build() *LogConfig
}

// Concrete Builder - 具体建造者
type ConcreteLogConfigBuilder struct {
	config *LogConfig
}

func NewLogConfigBuilder() *ConcreteLogConfigBuilder {
	return &ConcreteLogConfigBuilder{
		config: &LogConfig{
			Level:         "INFO",
			Format:        "text",
			Outputs:       make([]LogOutput, 0),
			Filters:       make([]LogFilter, 0),
			BufferSize:    1024,
			FlushInterval: 5 * time.Second,
			Timezone:      time.UTC,
			IncludeFields: make([]string, 0),
			ExcludeFields: make([]string, 0),
			Metadata:      make(map[string]interface{}),
		},
	}
}

func (b *ConcreteLogConfigBuilder) SetLevel(level string) LogConfigBuilder {
	b.config.Level = level
	return b
}

func (b *ConcreteLogConfigBuilder) SetFormat(format string) LogConfigBuilder {
	b.config.Format = format
	return b
}

func (b *ConcreteLogConfigBuilder) AddOutput(output LogOutput) LogConfigBuilder {
	b.config.Outputs = append(b.config.Outputs, output)
	return b
}

func (b *ConcreteLogConfigBuilder) AddFilter(filter LogFilter) LogConfigBuilder {
	b.config.Filters = append(b.config.Filters, filter)
	return b
}

func (b *ConcreteLogConfigBuilder) SetRotation(rotation RotationConfig) LogConfigBuilder {
	b.config.Rotation = rotation
	return b
}

func (b *ConcreteLogConfigBuilder) SetBuffer(size int, flushInterval time.Duration) LogConfigBuilder {
	b.config.BufferSize = size
	b.config.FlushInterval = flushInterval
	return b
}

func (b *ConcreteLogConfigBuilder) SetTimezone(timezone *time.Location) LogConfigBuilder {
	b.config.Timezone = timezone
	return b
}

func (b *ConcreteLogConfigBuilder) IncludeField(field string) LogConfigBuilder {
	b.config.IncludeFields = append(b.config.IncludeFields, field)
	return b
}

func (b *ConcreteLogConfigBuilder) ExcludeField(field string) LogConfigBuilder {
	b.config.ExcludeFields = append(b.config.ExcludeFields, field)
	return b
}

func (b *ConcreteLogConfigBuilder) SetMetadata(key string, value interface{}) LogConfigBuilder {
	b.config.Metadata[key] = value
	return b
}

func (b *ConcreteLogConfigBuilder) Build() *LogConfig {
	return b.config
}

// Director - 指挥者
type LogConfigDirector struct {
	builder LogConfigBuilder
}

func NewLogConfigDirector(builder LogConfigBuilder) *LogConfigDirector {
	return &LogConfigDirector{builder: builder}
}

func (d *LogConfigDirector) ConstructDevelopmentConfig() *LogConfig {
	return d.builder.
		SetLevel("DEBUG").
		SetFormat("text").
		AddOutput(LogOutput{
			Type:     "console",
			Target:   "stdout",
			Format:   "colored",
			MinLevel: "DEBUG",
		}).
		AddOutput(LogOutput{
			Type:     "file",
			Target:   "dev.log",
			Format:   "text",
			MinLevel: "INFO",
		}).
		SetBuffer(512, 1*time.Second).
		IncludeField("timestamp").
		IncludeField("level").
		IncludeField("message").
		IncludeField("caller").
		SetMetadata("environment", "development").
		Build()
}

func (d *LogConfigDirector) ConstructProductionConfig() *LogConfig {
	location, _ := time.LoadLocation("Asia/Shanghai")
	return d.builder.
		SetLevel("INFO").
		SetFormat("json").
		AddOutput(LogOutput{
			Type:     "file",
			Target:   "/var/log/app/app.log",
			Format:   "json",
			MinLevel: "INFO",
		}).
		AddFilter(LogFilter{
			Field:     "level",
			Operation: ">=",
			Value:     "INFO",
		}).
		SetRotation(RotationConfig{
			MaxSize:    100 * 1024 * 1024,
			MaxAge:     30 * 24 * time.Hour,
			MaxBackups: 10,
			Compress:   true,
		}).
		SetBuffer(4096, 10*time.Second).
		SetTimezone(location).
		IncludeField("timestamp").
		IncludeField("level").
		IncludeField("message").
		IncludeField("hostname").
		IncludeField("service").
		ExcludeField("debug_info").
		SetMetadata("environment", "production").
		SetMetadata("service", "web-api").
		Build()
}

// 使用演示
func main() {
	fmt.Println("=== 日志配置建造者演示 ===")

	// 开发环境配置
	logBuilder := NewLogConfigBuilder()
	logDirector := NewLogConfigDirector(logBuilder)

	devConfig := logDirector.ConstructDevelopmentConfig()
	fmt.Println("=== 开发环境配置 ===")
	devConfig.Display()
	fmt.Println()

	// 生产环境配置
	logBuilder = NewLogConfigBuilder()
	logDirector = NewLogConfigDirector(logBuilder)
	prodConfig := logDirector.ConstructProductionConfig()
	fmt.Println("=== 生产环境配置 ===")
	prodConfig.Display()
}
